﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace yysAuxiliary
{
    public class WinHelper
    {


        #region 各种API
        const int WM_ACTIVATEAPP = 0x001C; // WM_ACTIVATEAPP = $001C; 

        const int WM_MOUSEWHEEL = 0x020A; //鼠标滚轮
        const int WM_LBUTTONDOWN = 0x0201;//鼠标左键
        const int WM_LBUTTONUP = 0x0202; //释放鼠标左键 
        const int WM_KEYDOWN = 0x0100;//模拟按键
        const int WM_KEYUP = 0x0101;
        const int MOUSEEVENTF_MOVE = 0x0001;//用于琴台鼠标移动
        const int MOUSEEVENTF_LEFTDOWN = 0x0002;//前台鼠标单击
        const int MOUSEEVENTF_LEFTUP = 0x0004;
        const int WM_SETTEXT = 0x000C;//设置文字
        const int WM_GETTEXT = 0x000D;//读取文字
        const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter

        const int WM_MOUSEMOVE = 0x200;//移动鼠标时发生，同WM_MOUSEFIRST  



        [DllImport("user32.dll", EntryPoint = "GetForegroundWindow")]
        public static extern int GetForegroundWindow();
        [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern int SetForegroundWindow(int hwnd);


        [DllImport("User32")]
        private static extern int FindWindow(string className, string windowName);
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(int hWnd, int Msg, int wParam, string lParam);
        //[DllImport("User32.dll", EntryPoint = "SendMessage")]
        //private static extern int SendMessage(int hWnd, int Msg, int wParam, Point p);
        [DllImport("user32.dll")]//在窗口列表中寻找与指定条件相符的第一个子窗口
        private static extern int FindWindowEx(int hwndParent, // handle to parent window
                                                int hwndChildAfter, // handle to child window
                                                string className, //窗口类名            
                                                string windowName);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SetFocus(int hWnd);

        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
        [DllImport("gdi32.dll")]
        private static extern uint GetPixel(int hdc, int nXPos, int nYPos);

        [System.Runtime.InteropServices.DllImport("user32")]
        private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
        [DllImport("user32.dll")]
        private static extern bool SetCursorPos(int X, int Y);

        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);


        [DllImport("user32.dll")]
        private static extern bool SetWindowPos(int hWnd, int hWndlnsertAfter, int X, int Y, int cx, int cy, uint Flags);


        [DllImport("gdi32.dll")]
        private static extern IntPtr CreateDC(
         string lpszDriver,         // driver name驱动名
         string lpszDevice,         // device name设备名
         string lpszOutput,         // not used; should be NULL
         IntPtr lpInitData   // optional printer data
         );
        [DllImport("gdi32.dll")]
        private static extern int BitBlt(
         IntPtr hdcDest, // handle to destination DC目标设备的句柄
         int nXDest,   // x-coord of destination upper-left corner目标对象的左上角的X坐标
         int nYDest,   // y-coord of destination upper-left corner目标对象的左上角的Y坐标
         int nWidth,   // width of destination rectangle目标对象的矩形宽度
         int nHeight, // height of destination rectangle目标对象的矩形长度
         IntPtr hdcSrc,   // handle to source DC源设备的句柄
         int nXSrc,    // x-coordinate of source upper-left corner源对象的左上角的X坐标
         int nYSrc,    // y-coordinate of source upper-left corner源对象的左上角的Y坐标
         UInt32 dwRop   // raster operation code光栅的操作值
         );
        [DllImport("gdi32.dll")]
        private static extern IntPtr CreateCompatibleDC(
         IntPtr hdc // handle to DC
         );
        [DllImport("gdi32.dll")]
        private static extern IntPtr CreateCompatibleBitmap(
         IntPtr hdc,         // handle to DC
         int nWidth,      // width of bitmap, in pixels
         int nHeight      // height of bitmap, in pixels
         );
        [DllImport("gdi32.dll")]
        private static extern IntPtr SelectObject(
         IntPtr hdc,           // handle to DC
         IntPtr hgdiobj    // handle to object
         );
        [DllImport("gdi32.dll")]
        private static extern int DeleteDC(
         IntPtr hdc           // handle to DC
         );
        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
        [DllImport("user32.dll")]
        private static extern bool PrintWindow(
         IntPtr hwnd,                // Window to copy,Handle to the window that will be copied.
         IntPtr hdcBlt,              // HDC to print into,Handle to the device context.
         UInt32 nFlags               // Optional flags,Specifies the drawing options. It can be one of the following values.
         );
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowDC(
         IntPtr hwnd
         );
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetWindowRect(int hWnd, ref RECT lpRect);
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left; //最左坐标
            public int Top; //最上坐标
            public int Right; //最右坐标
            public int Bottom; //最下坐标
        }
        private static Bitmap GetWindowCapture(IntPtr hWnd)
        {
            IntPtr hscrdc = GetWindowDC(hWnd);
            RECT windowRect = new RECT();
            GetWindowRect(hWnd, ref windowRect);
            int width = windowRect.Right - windowRect.Left;
            int height = windowRect.Bottom - windowRect.Top;
            IntPtr hbitmap = CreateCompatibleBitmap(hscrdc, width, height);
            IntPtr hmemdc = CreateCompatibleDC(hscrdc);
            SelectObject(hmemdc, hbitmap);
            PrintWindow(hWnd, hmemdc, 0);
            Bitmap bmp = Bitmap.FromHbitmap(hbitmap);
            DeleteDC(hscrdc);//删除用过的对象
            DeleteDC(hmemdc);//删除用过的对象
            return bmp;
        }

        private static Bitmap CaptureWindow(IntPtr handle)
        {
            IntPtr hdcSrc = GetWindowDC(handle);
            RECT windowRect = new RECT();
            GetWindowRect(handle, ref windowRect);
            int width = windowRect.Right - windowRect.Left;
            int height = windowRect.Bottom - windowRect.Top;
            IntPtr hdcDest = CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = CreateCompatibleBitmap(hdcSrc, width, height);
            IntPtr hOld = SelectObject(hdcDest, hBitmap);
            BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, SRCCOPY);
            SelectObject(hdcDest, hOld);
            DeleteDC(hdcDest);
            ReleaseDC(handle, hdcSrc);
            Bitmap img = Image.FromHbitmap(hBitmap);
            DeleteObject(hBitmap);
            return img;
        }

        [DllImport("user32.dll", EntryPoint = "WindowFromPoint")]//指定坐标处窗体句柄
        private static extern int WindowFromPoint(
            int xPoint,
            int yPoint
        );
        [DllImport("user32.dll", EntryPoint = "WindowFromPoint")]//指定坐标处窗体句柄
        private static extern int WindowFromPoint(
            Point p
        );
        [DllImport("user32.dll", EntryPoint = "GetWindowText")]
        private static extern int GetWindowText(
            int hWnd,
            StringBuilder lpString,
            int nMaxCount
        );

        [DllImport("user32.dll", EntryPoint = "GetClassName")]
        private static extern int GetClassName(
            int hWnd,
            StringBuilder lpString,
            int nMaxCont
        );

        [DllImport("user32.dll")]
        static extern Int32 GetWindowLong(
            int hWnd,
            Int32 nIndex
        );
        [DllImport("user32.dll")]
        static extern Int32 SetWindowLong(
            int hWnd,
            Int32 nIndex,
            Int32 dwNewLong
        );
        /* 
     * 定义 Win32 常数 
     */
        const Int32 GWL_STYLE = -16;
        const Int32 WS_BORDER = (Int32)0x00800000L;
        const Int32 WS_THICKFRAME = (Int32)0x00040000L;
        const Int32 SWP_NOMOVE = 0x0002;
        const Int32 SWP_NOSIZE = 0x0001;
        const Int32 SWP_NOZORDER = 0x0004;
        const Int32 SWP_FRAMECHANGED = 0x0020;
        const Int32 SW_MAXIMIZE = 3;

        /// <summary>
        /// 设置目标窗体大小，位置
        /// </summary>
        /// <param name="hWnd">目标句柄</param>
        /// <param name="x">目标窗体新位置X轴坐标</param>
        /// <param name="y">目标窗体新位置Y轴坐标</param>
        /// <param name="nWidth">目标窗体新宽度</param>
        /// <param name="nHeight">目标窗体新高度</param>
        /// <param name="BRePaint">是否刷新窗体</param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int MoveWindow(int hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint);
        #endregion

        /// <summary>
        /// 程序句柄
        /// </summary>
        public static int winIntPtr = 0;

        /// <summary>
        /// 根据title获取句柄
        /// </summary>
        /// <param name="titleName"></param>
        /// <returns></returns>
        public static int GetWindow(string titleName)
        {
            return FindWindow(null, titleName);
        }

        /// <summary>
        /// 点击带漂移
        /// </summary>
        /// <param name="p"></param>
        public static void SendCheck(Point p, int offset)
        {
            Random r = new Random();
            p.X = p.X + r.Next(offset);
            p.Y = p.Y + ConfigData.Current.Offsetheight + r.Next(offset);//+是为了去除标题栏的高度，不能包含
            SendCheck(p);
        }


        /// <summary>
        /// 点击
        /// </summary>
        /// <param name="p"></param>
        public static void SendCheck(Point p)
        {
            //SetForegroundWindow(winIntPtr);
            //SendMessage(winIntPtr, WM_ACTIVATEAPP, 0, 1);
            //SetFocus(winIntPtr);
            SendMessage(winIntPtr, WM_LBUTTONDOWN, 0, ((p.Y) << 16 | (p.X)));
            SendMessage(winIntPtr, WM_LBUTTONUP, 0, ((p.Y) << 16 | (p.X)));
        }



        /// <summary>
        /// 获取图像
        /// </summary>
        /// <returns></returns>
        public static Bitmap GetBitmap()
        {
            //return GetWindowCapture(new IntPtr(winIntPtr));
            return CaptureWindow(new IntPtr(winIntPtr));
        }

        /// <summary>
        /// 通过坐标获取句柄
        /// </summary>
        /// <param name="p"></param>
        public static int GetHwnd(Point p)
        {
            return WindowFromPoint(p);
        }

        /// <summary>
        /// 通过句柄获取名
        /// </summary>
        /// <param name="p"></param>
        public static string GetTitle()
        {
            StringBuilder name = new StringBuilder(256);
            GetWindowText(winIntPtr, name, 256);
            return name.ToString();
        }

        /// <summary>
        /// 设置大小
        /// </summary>
        /// <param name="w">宽</param>
        /// <param name="h">高</param>
        /// <returns></returns>
        public static bool SetSize(int w, int h)
        {
            return SetWindowPos(winIntPtr, 1, 0, 0, w, h, 2 | 80);
        }

        /// <summary>
        /// 设置顶级窗体大小
        /// </summary>
        /// <param name="w">宽</param>
        /// <param name="h">高</param>
        /// <returns></returns>
        public static bool SetTopWindowSize(int w, int h)
        {
            var topwindow = Win32Api.GetTopWindow((IntPtr)winIntPtr);
            return SetWindowPos((int)topwindow, 1, 0, 0, w, h, 2 | 80);
        }

        /// <summary>
        /// 设置边框样式
        /// </summary>
        /// <param name="w">宽</param>
        /// <param name="h">高</param>
        /// <returns></returns>
        public static void SetStyle()
        {
            // 除去窗体边框. 
            Int32 wndStyle = GetWindowLong(winIntPtr, GWL_STYLE);
            wndStyle &= ~WS_BORDER;
            wndStyle &= ~WS_THICKFRAME;
            SetWindowLong(winIntPtr, GWL_STYLE, wndStyle);
            SetWindowPos(winIntPtr, 0, 0, 0, 0, 0,
              SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
        }

        public static void MoveWindow(int x, int y, int w, int h)
        {
            MoveWindow(winIntPtr, x, y, w, h, true);
        }
    }
}
